# =============================================================================
# April 24 2025
# R code used to produce all results, tables, and figures in the SI Online Appendix I
# Rebecca Cordell
# Unpacking the Role of In-Group Bias in US Public Opinion on Human Rights Violations
# American Journal of Political Science
# https://doi.org/10.7910/DVN/TGAL7M
# =============================================================================

# Clear work environment
rm(list=ls())

# Install Packages
#install.packages("dplyr")
#install.packages("ggplot2")
#install.packages("forcats")
#install.packages("ggpubr")
#install.packages("ggeasy")
#install.packages("lemon")
#install.packages("sandwich")
#install.packages("survey")
#install.packages("lmtest")
#install.packages("remotes")
#remotes::install_version("cregg", version = "0.4.0")

# Required Packages
library("dplyr")
library("ggplot2")
library("forcats")
library("ggpubr")
library("sandwich")
library("survey")
library("lmtest")
library("cregg")
library("ggeasy")
library("lemon")

options(scipen = 999)
options(warn=-1)

# -----------------------------------------------------------------------------
# Read in data
# -----------------------------------------------------------------------------

hr_survey<-read.csv("cordell_ingroupbiashumanrights_data.csv", header=TRUE, stringsAsFactors = FALSE)

# =============================================================================
# Figure I.1: Interaction Effects Target (Race), Respondents’ Disapproval
# =============================================================================

# Convert regression variables into factors
factor_vars <- c("agent", "type", "scope", "targ_nonstate",
                 "perp_match", "targ_relig_match", "targ_citiz_match",
                 "frame", "elite_match", "targ_race_perp", "targ_race_relig", 
                 "targ_race_citiz", "targ_race_elite","targ_race_match")
hr_survey[factor_vars] <- lapply(hr_survey[factor_vars], as.factor)

# -----------------------------------------------------------------------------
# Calculate marginal means interactions
# -----------------------------------------------------------------------------

# Model 1
fig_i1_m1 <- cregg::cj(hr_survey, outcome1 ~ agent + type + scope + targ_nonstate + perp_match + targ_relig_match + targ_citiz_match + frame + elite_match + targ_race_perp + targ_race_relig + targ_race_citiz + targ_race_elite, id = ~id, estimate = "mm", by = ~targ_race_match)

# Model 2
fig_i1_m2 <- cregg::cj(hr_survey, outcome2 ~ agent + type + scope + targ_nonstate + perp_match + targ_relig_match + targ_citiz_match + frame + elite_match + targ_race_perp + targ_race_relig + targ_race_citiz + targ_race_elite, id = ~id, estimate = "mm", by = ~targ_race_match)

# Subset group identity dummy variables
interaction_terms <- c("targ_race_perp", "targ_race_relig", "targ_race_citiz", "targ_race_elite")
fig_i1_m1 <- fig_i1_m1[fig_i1_m1$feature %in% interaction_terms,]
fig_i1_m2 <- fig_i1_m2[fig_i1_m2$feature %in% interaction_terms,]

# Exclude NA values
fig_i1_m1 <- fig_i1_m1[!is.na(fig_i1_m1$estimate),]
fig_i1_m2 <- fig_i1_m2[!is.na(fig_i1_m2$estimate),]

# -----------------------------------------------------------------------------
# Prepare Figures
# -----------------------------------------------------------------------------

# Combine models
fig_i1_all <- rbind(fig_i1_m1, fig_i1_m2) 

# Create group identity variable labels
variable_labels <- c("perp_match" = "Perpetrator (partisanship)",
                     "targ_relig_match" = "Target (religion)",
                     "targ_citiz_match" = "Target (citizenship)",
                     "elite_match" = "Elite cue (partisanship)"
)
fig_i1_all <- dplyr::bind_rows(
  fig_i1_all,
  do.call(rbind, lapply(names(variable_labels), function(variable) {
    data.frame(
      outcome = c("outcome1", "outcome2"),
      variable = variable_labels[variable],
      level = variable_labels[variable],
      estimate = NA, lower = NA, upper = NA
    )
  }))
)

# Set factor order
fig_i1_all_race_in <- filter(fig_i1_all, !grepl("race_out", level))
fig_i1_all_race_in <- fig_i1_all_race_in %>%
  mutate(level = factor(level, levels = c("Perpetrator (partisanship)", "race_in_perp_in", "race_in_perp_out",
                                          "Target (religion)", "race_in_relig_in", "race_in_relig_out",
                                          "Target (citizenship)", "race_in_citiz_in", "race_in_citiz_out",
                                          "Elite cue (partisanship)", "race_in_elite_in", "race_in_elite_out")) %>% fct_rev())
fig_i1_all_race_out <- filter(fig_i1_all, !grepl("race_in", level))
fig_i1_all_race_out <- fig_i1_all_race_out %>%
  mutate(level = factor(level, levels = c("Perpetrator (partisanship)", "race_out_perp_in", "race_out_perp_out",
                                          "Target (religion)", "race_out_relig_in", "race_out_relig_out",
                                          "Target (citizenship)", "race_out_citiz_in", "race_out_citiz_out",
                                          "Elite cue (partisanship)", "race_out_elite_in", "race_out_elite_out")) %>% fct_rev())

# Create respondents variable (in-groups vs. out-groups)
fig_i1_all_race_in <- fig_i1_all_race_in %>%
  mutate(Respondents = case_when(
    grepl("_in$", level) ~ "In-group",   
    grepl("_out$", level) ~ "Out-group", 
    level %in% c("Perpetrator (partisanship)", "Target (religion)", 
                 "Target (citizenship)", "Elite cue (partisanship)") ~ "In-group", 
    TRUE ~ level
  )) %>%
  mutate(Respondents = factor(Respondents, levels = c("In-group", "Out-group")))
fig_i1_all_race_out <- fig_i1_all_race_out %>%
  mutate(Respondents = case_when(
    grepl("_out$", level) ~ "Out-group",  
    grepl("_in$", level) ~ "In-group",  
    level %in% c("Perpetrator (partisanship)", "Target (religion)", 
                 "Target (citizenship)", "Elite cue (partisanship)") ~ "In-group", 
    TRUE ~ level
  )) %>%
  mutate(Respondents = factor(Respondents, levels = c("In-group", "Out-group")))

# Separate models
fig_i1_m1_race_in <- filter(fig_i1_all_race_in, outcome == "outcome1")
fig_i1_m2_race_in <- filter(fig_i1_all_race_in, outcome == "outcome2")
fig_i1_m1_race_out <- filter(fig_i1_all_race_out, outcome == "outcome1")
fig_i1_m2_race_out <- filter(fig_i1_all_race_out, outcome == "outcome2")

# -----------------------------------------------------------------------------
# Create Figures
# -----------------------------------------------------------------------------

# Create panel (a) Target (race) in-group - disapproval forced-choice
fig_i1_m1_race_in_plot <- ggplot(fig_i1_m1_race_in, aes(x = level, y = estimate, colour = Respondents)) +
  geom_point() +
  geom_errorbar(aes(ymin = lower, ymax = upper), size = 0.3, width = 0.2) +
  scale_x_discrete(labels = c(
    "", "Elite cue (partisanship)", "", 
    "", "Target (citizenship)", "", 
    "", "Target (religion)", "", 
    "", "Perpetrator (partisanship)", ""
  )) +
  xlab('') + ylab('Marginal mean') +
  coord_flip() +
  geom_hline(yintercept = 0.5, size = 0.2, color = "black") +
  scale_y_symmetric(mid = 0.5) +
  theme_classic(base_size = 10) +
  scale_colour_grey() +
  easy_center_title() +
  ggtitle("(a) Disapproval forced-choice") +
  theme(
    axis.text.x = element_text(colour = "black"),
    axis.text.y = element_text(colour = "black"),
    axis.title.x = element_text(margin = margin(t = 10)),
    axis.ticks.y = element_blank(),
    legend.position = "none"
  ) +
  labs(color = NULL)

# Create panel (b) Target (race) in-group - disapproval ratings-based
fig_i1_m2_race_in_plot <- ggplot(fig_i1_m2_race_in, aes(x = level, y = estimate, colour = Respondents)) +
  geom_point() +
  geom_errorbar(aes(ymin = lower, ymax = upper), size = 0.3, width = 0.2) +
  scale_x_discrete(labels = c(
    "", "Elite cue (partisanship)", "", 
    "", "Target (citizenship)", "", 
    "", "Target (religion)", "", 
    "", "Perpetrator (partisanship)", ""
  )) +
  xlab('') + ylab('Marginal mean') +
  coord_flip(ylim=c(0.66, 0.75)) +
  theme_classic(base_size = 10) +
  scale_colour_grey() +
  easy_center_title() +
  ggtitle("(b) Disapproval ratings-based") +
  theme(
    axis.text.x = element_text(colour = "black"),
    axis.text.y = element_text(colour = "black"),
    axis.title.x = element_text(margin = margin(t = 10)),
    axis.ticks.y = element_blank(),
    legend.position = "none"
  ) +
  labs(color = NULL)

# Create panel (c) Target (race) out-group - disapproval forced choice
fig_i1_m1_race_out_plot <- ggplot(fig_i1_m1_race_out, aes(x = level, y = estimate, colour = Respondents)) +
  geom_point() +
  geom_errorbar(aes(ymin = lower, ymax = upper), size = 0.3, width = 0.2) +
  scale_x_discrete(labels = c(
    "", "Elite cue (partisanship)", "", 
    "", "Target (citizenship)", "", 
    "", "Target (religion)", "", 
    "", "Perpetrator (partisanship)", ""
  )) +
  xlab('') + ylab('Marginal mean') +
  coord_flip() +
  geom_hline(yintercept = 0.5, size = 0.2, color = "black") +
  scale_y_symmetric(mid = 0.5) +
  theme_classic(base_size = 10) +
  scale_colour_grey() +
  easy_center_title() +
  ggtitle("(c) Disapproval forced-choice") +
  theme(
    axis.text.x = element_text(colour = "black"),
    axis.text.y = element_text(colour = "black"),
    axis.title.x = element_text(margin = margin(t = 10)),
    axis.ticks.y = element_blank()
  ) +
  labs(color = NULL)

# Create panel (d) Target (race) out-group - disapproval ratings-based
fig_i1_m2_race_out_plot <- ggplot(fig_i1_m2_race_out, aes(x = level, y = estimate, colour = Respondents)) +
  geom_point() +
  geom_errorbar(aes(ymin = lower, ymax = upper), size = 0.3, width = 0.2) +
  scale_x_discrete(labels = c(
    "", "Elite cue (partisanship)", "", 
    "", "Target (citizenship)", "", 
    "", "Target (religion)", "", 
    "", "Perpetrator (partisanship)", ""
  )) +
  xlab('') + ylab('Marginal mean') +
  coord_flip(ylim=c(0.66, 0.75)) +
  theme_classic(base_size = 10) +
  scale_colour_grey() +
  easy_center_title() +
  ggtitle("(d) Disapproval ratings-based") +
  theme(
    axis.text.x = element_text(colour = "black"),
    axis.text.y = element_text(colour = "black"),
    axis.title.x = element_text(margin = margin(t = 10)),
    axis.ticks.y = element_blank()
  ) +
  labs(color = NULL)

# Print Figure I.1
fig_i1_race_in_plot<-ggarrange(fig_i1_m1_race_in_plot, NULL, fig_i1_m2_race_in_plot,
                               nrow = 1, common.legend = F, legend = NULL, ncol = 3, widths = c(1, 0.09, 1))
fig_i1_race_in_plot<-annotate_figure(fig_i1_race_in_plot, top = text_grob("Target (race) in-group", size = 14))

fig_i1_race_out_plot<-ggarrange(fig_i1_m1_race_out_plot, NULL, fig_i1_m2_race_out_plot,
                                nrow = 1, common.legend = T, legend = "bottom", ncol = 3, widths = c(1, 0.09, 1))
fig_i1_race_out_plot<-annotate_figure(fig_i1_race_out_plot, top = text_grob("Target (race) out-group", size = 14))
pdf('figure_i1.pdf', width = 8.26, height = 5.82)
ggarrange(fig_i1_race_in_plot, fig_i1_race_out_plot,
          nrow = 2, common.legend = T, legend = "bottom", ncol=1, heights = c(1, 1.1))
dev.off()

# =============================================================================
# Figure I.2: Interaction Effects Target (Religion), Respondents’ Disapproval
# =============================================================================

# Convert regression variables into factors
factor_vars <- c("agent", "type", "scope", "targ_nonstate",
                 "perp_match", "targ_race_match", "targ_citiz_match",
                 "frame", "elite_match", "targ_relig_perp", "targ_relig_race", 
                 "targ_relig_citiz", "targ_relig_elite","targ_relig_match")
hr_survey[factor_vars] <- lapply(hr_survey[factor_vars], as.factor)

# -----------------------------------------------------------------------------
# Calculate marginal means interactions
# -----------------------------------------------------------------------------

# Model 1
fig_i2_m1 <- cregg::cj(hr_survey, outcome1 ~ agent + type + scope + targ_nonstate + perp_match + targ_race_match + targ_citiz_match + frame + elite_match + targ_relig_perp + targ_relig_race + targ_relig_citiz + targ_relig_elite, id = ~id, estimate = "mm", by = ~targ_relig_match)

# Model 2
fig_i2_m2 <- cregg::cj(hr_survey, outcome2 ~ agent + type + scope + targ_nonstate + perp_match + targ_race_match + targ_citiz_match + frame + elite_match + targ_relig_perp + targ_relig_race + targ_relig_citiz + targ_relig_elite, id = ~id, estimate = "mm", by = ~targ_relig_match)

# Subset group identity dummy variables
interaction_terms <- c("targ_relig_perp", "targ_relig_race", "targ_relig_citiz", "targ_relig_elite")
fig_i2_m1 <- fig_i2_m1[fig_i2_m1$feature %in% interaction_terms,]
fig_i2_m2 <- fig_i2_m2[fig_i2_m2$feature %in% interaction_terms,]

# Exclude NA values
fig_i2_m1 <- fig_i2_m1[!is.na(fig_i2_m1$estimate),]
fig_i2_m2 <- fig_i2_m2[!is.na(fig_i2_m2$estimate),]

# -----------------------------------------------------------------------------
# Prepare Figures
# -----------------------------------------------------------------------------

# Combine models
fig_i2_all <- rbind(fig_i2_m1, fig_i2_m2) 

# Create group identity variable labels
variable_labels <- c("perp_match" = "Perpetrator (partisanship)",
                     "targ_race_match" = "Target (race)",
                     "targ_citiz_match" = "Target (citizenship)",
                     "elite_match" = "Elite cue (partisanship)"
)
fig_i2_all <- dplyr::bind_rows(
  fig_i2_all,
  do.call(rbind, lapply(names(variable_labels), function(variable) {
    data.frame(
      outcome = c("outcome1", "outcome2"),
      variable = variable_labels[variable],
      level = variable_labels[variable],
      estimate = NA, lower = NA, upper = NA
    )
  }))
)

# Set factor order
fig_i2_all_relig_in <- filter(fig_i2_all, !grepl("relig_out", level))
fig_i2_all_relig_in <- fig_i2_all_relig_in %>%
  mutate(level = factor(level, levels = c("Perpetrator (partisanship)", "relig_in_perp_in", "relig_in_perp_out",
                                          "Target (race)", "relig_in_race_in", "relig_in_race_out",
                                          "Target (citizenship)", "relig_in_citiz_in", "relig_in_citiz_out",
                                          "Elite cue (partisanship)", "relig_in_elite_in", "relig_in_elite_out")) %>% fct_rev())
fig_i2_all_relig_out <- filter(fig_i2_all, !grepl("relig_in", level))
fig_i2_all_relig_out <- fig_i2_all_relig_out %>%
  mutate(level = factor(level, levels = c("Perpetrator (partisanship)", "relig_out_perp_in", "relig_out_perp_out",
                                          "Target (race)", "relig_out_race_in", "relig_out_race_out",
                                          "Target (citizenship)", "relig_out_citiz_in", "relig_out_citiz_out",
                                          "Elite cue (partisanship)", "relig_out_elite_in", "relig_out_elite_out")) %>% fct_rev())

# Create respondents variable (in-groups vs. out-groups)
fig_i2_all_relig_in <- fig_i2_all_relig_in %>%
  mutate(Respondents = case_when(
    grepl("_in$", level) ~ "In-group",   
    grepl("_out$", level) ~ "Out-group", 
    level %in% c("Perpetrator (partisanship)", "Target (race)", 
                 "Target (citizenship)", "Elite cue (partisanship)") ~ "In-group", 
    TRUE ~ level
  )) %>%
  mutate(Respondents = factor(Respondents, levels = c("In-group", "Out-group")))
fig_i2_all_relig_out <- fig_i2_all_relig_out %>%
  mutate(Respondents = case_when(
    grepl("_out$", level) ~ "Out-group",  
    grepl("_in$", level) ~ "In-group",  
    level %in% c("Perpetrator (partisanship)", "Target (race)", 
                 "Target (citizenship)", "Elite cue (partisanship)") ~ "In-group", 
    TRUE ~ level
  )) %>%
  mutate(Respondents = factor(Respondents, levels = c("In-group", "Out-group")))

# Separate models
fig_i2_m1_relig_in <- filter(fig_i2_all_relig_in, outcome == "outcome1")
fig_i2_m2_relig_in <- filter(fig_i2_all_relig_in, outcome == "outcome2")
fig_i2_m1_relig_out <- filter(fig_i2_all_relig_out, outcome == "outcome1")
fig_i2_m2_relig_out <- filter(fig_i2_all_relig_out, outcome == "outcome2")

# -----------------------------------------------------------------------------
# Create Figures
# -----------------------------------------------------------------------------

# Create panel (a) Target (religion) in-group - disapproval forced-choice
fig_i2_m1_relig_in_plot <- ggplot(fig_i2_m1_relig_in, aes(x = level, y = estimate, colour = Respondents)) +
  geom_point() +
  geom_errorbar(aes(ymin = lower, ymax = upper), size = 0.3, width = 0.2) +
  scale_x_discrete(labels = c(
    "", "Elite cue (partisanship)", "", 
    "", "Target (citizenship)", "", 
    "", "Target (race)", "", 
    "", "Perpetrator (partisanship)", ""
  )) +
  xlab('') + ylab('Marginal mean') +
  coord_flip() +
  geom_hline(yintercept = 0.5, size = 0.2, color = "black") +
  scale_y_symmetric(mid = 0.5) +
  theme_classic(base_size = 10) +
  scale_colour_grey() +
  easy_center_title() +
  ggtitle("(a) Disapproval forced-choice") +
  theme(
    axis.text.x = element_text(colour = "black"),
    axis.text.y = element_text(colour = "black"),
    axis.title.x = element_text(margin = margin(t = 10)),
    axis.ticks.y = element_blank(),
    legend.position = "none"
  ) +
  labs(color = NULL)

# Create panel (b) Target (religion) in-group - disapproval ratings-based
fig_i2_m2_relig_in_plot <- ggplot(fig_i2_m2_relig_in, aes(x = level, y = estimate, colour = Respondents)) +
  geom_point() +
  geom_errorbar(aes(ymin = lower, ymax = upper), size = 0.3, width = 0.2) +
  scale_x_discrete(labels = c(
    "", "Elite cue (partisanship)", "", 
    "", "Target (citizenship)", "", 
    "", "Target (race)", "", 
    "", "Perpetrator (partisanship)", ""
  )) +
  xlab('') + ylab('Marginal mean') +
  coord_flip(ylim=c(0.65, 0.72)) +
  theme_classic(base_size = 10) +
  scale_colour_grey() +
  easy_center_title() +
  ggtitle("(b) Disapproval ratings-based") +
  theme(
    axis.text.x = element_text(colour = "black"),
    axis.text.y = element_text(colour = "black"),
    axis.title.x = element_text(margin = margin(t = 10)),
    axis.ticks.y = element_blank(),
    legend.position = "none"
  ) +
  labs(color = NULL)

# Create panel (c) Target (religion) out-group - disapproval forced choice
fig_i2_m1_relig_out_plot <- ggplot(fig_i2_m1_relig_out, aes(x = level, y = estimate, colour = Respondents)) +
  geom_point() +
  geom_errorbar(aes(ymin = lower, ymax = upper), size = 0.3, width = 0.2) +
  scale_x_discrete(labels = c(
    "", "Elite cue (partisanship)", "", 
    "", "Target (citizenship)", "", 
    "", "Target (race)", "", 
    "", "Perpetrator (partisanship)", ""
  )) +
  xlab('') + ylab('Marginal mean') +
  coord_flip() +
  geom_hline(yintercept = 0.5, size = 0.2, color = "black") +
  scale_y_symmetric(mid = 0.5) +
  theme_classic(base_size = 10) +
  scale_colour_grey() +
  easy_center_title() +
  ggtitle("(c) Disapproval forced-choice") +
  theme(
    axis.text.x = element_text(colour = "black"),
    axis.text.y = element_text(colour = "black"),
    axis.title.x = element_text(margin = margin(t = 10)),
    axis.ticks.y = element_blank()
  ) +
  labs(color = NULL)

# Create panel (d) Target (religion) out-group - disapproval ratings-based
fig_i2_m2_relig_out_plot <- ggplot(fig_i2_m2_relig_out, aes(x = level, y = estimate, colour = Respondents)) +
  geom_point() +
  geom_errorbar(aes(ymin = lower, ymax = upper), size = 0.3, width = 0.2) +
  scale_x_discrete(labels = c(
    "", "Elite cue (partisanship)", "", 
    "", "Target (citizenship)", "", 
    "", "Target (race)", "", 
    "", "Perpetrator (partisanship)", ""
  )) +
  xlab('') + ylab('Marginal mean') +
  coord_flip(ylim=c(0.65, 0.72)) +
  theme_classic(base_size = 10) +
  scale_colour_grey() +
  easy_center_title() +
  ggtitle("(d) Disapproval ratings-based") +
  theme(
    axis.text.x = element_text(colour = "black"),
    axis.text.y = element_text(colour = "black"),
    axis.title.x = element_text(margin = margin(t = 10)),
    axis.ticks.y = element_blank()
  ) +
  labs(color = NULL)

# Print Figure I.2
fig_i2_relig_in_plot<-ggarrange(fig_i2_m1_relig_in_plot, NULL, fig_i2_m2_relig_in_plot,
                                nrow = 1, common.legend = F, legend = NULL, ncol = 3, widths = c(1, 0.09, 1))
fig_i2_relig_in_plot<-annotate_figure(fig_i2_relig_in_plot, top = text_grob("Target (religion) in-group", size = 14))
fig_i2_relig_out_plot<-ggarrange(fig_i2_m1_relig_out_plot, NULL, fig_i2_m2_relig_out_plot,
                                 nrow = 1, common.legend = T, legend = "bottom", ncol = 3, widths = c(1, 0.09, 1))
fig_i2_relig_out_plot<-annotate_figure(fig_i2_relig_out_plot, top = text_grob("Target (religion) out-group", size = 14))
pdf('figure_i2.pdf', width = 8.26, height = 5.82)
ggarrange(fig_i2_relig_in_plot, fig_i2_relig_out_plot,
          nrow = 2, common.legend = T, legend = "bottom", ncol=1, heights = c(1, 1.1))
dev.off()

# =============================================================================
# Figure I.3: Interaction Effects Target (Citizenship), Respondents’ Disapproval
# =============================================================================

# Convert regression variables into factors
factor_vars <- c("agent", "type", "scope", "targ_nonstate",
                 "perp_match", "targ_race_match", "targ_relig_match",
                 "frame", "elite_match", "targ_citiz_perp", "targ_citiz_race", 
                 "targ_citiz_relig", "targ_citiz_elite","targ_citiz_match")
hr_survey[factor_vars] <- lapply(hr_survey[factor_vars], as.factor)

# -----------------------------------------------------------------------------
# Calculate marginal means interactions
# -----------------------------------------------------------------------------

# Model 1
fig_i3_m1 <- cregg::cj(hr_survey, outcome1 ~ agent + type + scope + targ_nonstate + perp_match + targ_race_match + targ_relig_match + frame + elite_match + targ_citiz_perp + targ_citiz_race + targ_citiz_relig + targ_citiz_elite, id = ~id, estimate = "mm", by = ~targ_citiz_match)

# Model 2
fig_i3_m2 <- cregg::cj(hr_survey, outcome2 ~ agent + type + scope + targ_nonstate + perp_match + targ_race_match + targ_relig_match + frame + elite_match + targ_citiz_perp + targ_citiz_race + targ_citiz_relig + targ_citiz_elite, id = ~id, estimate = "mm", by = ~targ_citiz_match)

# Subset group identity dummy variables
interaction_terms <- c("targ_citiz_perp", "targ_citiz_race", "targ_citiz_relig", "targ_citiz_elite")
fig_i3_m1 <- fig_i3_m1[fig_i3_m1$feature %in% interaction_terms,]
fig_i3_m2 <- fig_i3_m2[fig_i3_m2$feature %in% interaction_terms,]

# Exclude NA values
fig_i3_m1 <- fig_i3_m1[!is.na(fig_i3_m1$estimate),]
fig_i3_m2 <- fig_i3_m2[!is.na(fig_i3_m2$estimate),]

# -----------------------------------------------------------------------------
# Prepare Figures
# -----------------------------------------------------------------------------

# Combine models
fig_i3_all <- rbind(fig_i3_m1, fig_i3_m2) 

# Create group identity variable labels
variable_labels <- c("perp_match" = "Perpetrator (partisanship)",
                     "targ_race_match" = "Target (race)",
                     "targ_citiz_match" = "Target (religion)",
                     "elite_match" = "Elite cue (partisanship)"
)
fig_i3_all <- dplyr::bind_rows(
  fig_i3_all,
  do.call(rbind, lapply(names(variable_labels), function(variable) {
    data.frame(
      outcome = c("outcome1", "outcome2"),
      variable = variable_labels[variable],
      level = variable_labels[variable],
      estimate = NA, lower = NA, upper = NA
    )
  }))
)

# Set factor order
fig_i3_all_citiz_in <- filter(fig_i3_all, !grepl("citiz_out", level))
fig_i3_all_citiz_in <- fig_i3_all_citiz_in %>%
  mutate(level = factor(level, levels = c("Perpetrator (partisanship)", "citiz_in_perp_in", "citiz_in_perp_out",
                                          "Target (race)", "citiz_in_race_in", "citiz_in_race_out",
                                          "Target (religion)", "citiz_in_relig_in", "citiz_in_relig_out",
                                          "Elite cue (partisanship)", "citiz_in_elite_in", "citiz_in_elite_out")) %>% fct_rev())
fig_i3_all_citiz_out <- filter(fig_i3_all, !grepl("citiz_in", level))
fig_i3_all_citiz_out <- fig_i3_all_citiz_out %>%
  mutate(level = factor(level, levels = c("Perpetrator (partisanship)", "citiz_out_perp_in", "citiz_out_perp_out",
                                          "Target (race)", "citiz_out_race_in", "citiz_out_race_out",
                                          "Target (religion)", "citiz_out_relig_in", "citiz_out_relig_out",
                                          "Elite cue (partisanship)", "citiz_out_elite_in", "citiz_out_elite_out")) %>% fct_rev())

# Create respondents variable (in-groups vs. out-groups)
fig_i3_all_citiz_in <- fig_i3_all_citiz_in %>%
  mutate(Respondents = case_when(
    grepl("_in$", level) ~ "In-group",   
    grepl("_out$", level) ~ "Out-group", 
    level %in% c("Perpetrator (partisanship)", "Target (race)", 
                 "Target (religion)", "Elite cue (partisanship)") ~ "In-group", 
    TRUE ~ level
  )) %>%
  mutate(Respondents = factor(Respondents, levels = c("In-group", "Out-group")))
fig_i3_all_citiz_out <- fig_i3_all_citiz_out %>%
  mutate(Respondents = case_when(
    grepl("_out$", level) ~ "Out-group",  
    grepl("_in$", level) ~ "In-group",  
    level %in% c("Perpetrator (partisanship)", "Target (race)", 
                 "Target (religion)", "Elite cue (partisanship)") ~ "In-group", 
    TRUE ~ level
  )) %>%
  mutate(Respondents = factor(Respondents, levels = c("In-group", "Out-group")))

# Separate models
fig_i3_m1_citiz_in <- filter(fig_i3_all_citiz_in, outcome == "outcome1")
fig_i3_m2_citiz_in <- filter(fig_i3_all_citiz_in, outcome == "outcome2")
fig_i3_m1_citiz_out <- filter(fig_i3_all_citiz_out, outcome == "outcome1")
fig_i3_m2_citiz_out <- filter(fig_i3_all_citiz_out, outcome == "outcome2")

# -----------------------------------------------------------------------------
# Create Figures
# -----------------------------------------------------------------------------

# Create panel (a) Target (citizenship) in-group - disapproval forced-choice
fig_i3_m1_citiz_in_plot <- ggplot(fig_i3_m1_citiz_in, aes(x = level, y = estimate, colour = Respondents)) +
  geom_point() +
  geom_errorbar(aes(ymin = lower, ymax = upper), size = 0.3, width = 0.2) +
  scale_x_discrete(labels = c(
    "", "Elite cue (partisanship)", "", 
    "", "Target (religion)", "", 
    "", "Target (race)", "", 
    "", "Perpetrator (partisanship)", ""
  )) +
  xlab('') + ylab('Marginal mean') +
  coord_flip() +
  geom_hline(yintercept = 0.5, size = 0.2, color = "black") +
  scale_y_symmetric(mid = 0.5) +
  theme_classic(base_size = 10) +
  scale_colour_grey() +
  easy_center_title() +
  ggtitle("(a) Disapproval forced-choice") +
  theme(
    axis.text.x = element_text(colour = "black"),
    axis.text.y = element_text(colour = "black"),
    axis.title.x = element_text(margin = margin(t = 10)),
    axis.ticks.y = element_blank(),
    legend.position = "none"
  ) +
  labs(color = NULL)

# Create panel (b) Target (citizenship) in-group - disapproval ratings-based
fig_i3_m2_citiz_in_plot <- ggplot(fig_i3_m2_citiz_in, aes(x = level, y = estimate, colour = Respondents)) +
  geom_point() +
  geom_errorbar(aes(ymin = lower, ymax = upper), size = 0.3, width = 0.2) +
  scale_x_discrete(labels = c(
    "", "Elite cue (partisanship)", "", 
    "", "Target (religion)", "", 
    "", "Target (race)", "", 
    "", "Perpetrator (partisanship)", ""
  )) +
  xlab('') + ylab('Marginal mean') +
  coord_flip(ylim=c(0.66, 0.74)) +
  theme_classic(base_size = 10) +
  scale_colour_grey() +
  easy_center_title() +
  ggtitle("(b) Disapproval ratings-based") +
  theme(
    axis.text.x = element_text(colour = "black"),
    axis.text.y = element_text(colour = "black"),
    axis.title.x = element_text(margin = margin(t = 10)),
    axis.ticks.y = element_blank(),
    legend.position = "none"
  ) +
  labs(color = NULL)

# Create panel (c) Target (citizenship) out-group - disapproval forced choice
fig_i3_m1_citiz_out_plot <- ggplot(fig_i3_m1_citiz_out, aes(x = level, y = estimate, colour = Respondents)) +
  geom_point() +
  geom_errorbar(aes(ymin = lower, ymax = upper), size = 0.3, width = 0.2) +
  scale_x_discrete(labels = c(
    "", "Elite cue (partisanship)", "", 
    "", "Target (religion)", "", 
    "", "Target (race)", "", 
    "", "Perpetrator (partisanship)", ""
  )) +
  xlab('') + ylab('Marginal mean') +
  coord_flip() +
  geom_hline(yintercept = 0.5, size = 0.2, color = "black") +
  scale_y_symmetric(mid = 0.5) +
  theme_classic(base_size = 10) +
  scale_colour_grey() +
  easy_center_title() +
  ggtitle("(c) Disapproval forced-choice") +
  theme(
    axis.text.x = element_text(colour = "black"),
    axis.text.y = element_text(colour = "black"),
    axis.title.x = element_text(margin = margin(t = 10)),
    axis.ticks.y = element_blank()
  ) +
  labs(color = NULL)

# Create panel (d) Target (citizenship) out-group - disapproval ratings-based
fig_i3_m2_citiz_out_plot <- ggplot(fig_i3_m2_citiz_out, aes(x = level, y = estimate, colour = Respondents)) +
  geom_point() +
  geom_errorbar(aes(ymin = lower, ymax = upper), size = 0.3, width = 0.2) +
  scale_x_discrete(labels = c(
    "", "Elite cue (partisanship)", "", 
    "", "Target (religion)", "", 
    "", "Target (race)", "", 
    "", "Perpetrator (partisanship)", ""
  )) +
  xlab('') + ylab('Marginal mean') +
  coord_flip(ylim=c(0.66, 0.74)) +
  theme_classic(base_size = 10) +
  scale_colour_grey() +
  easy_center_title() +
  ggtitle("(d) Disapproval ratings-based") +
  theme(
    axis.text.x = element_text(colour = "black"),
    axis.text.y = element_text(colour = "black"),
    axis.title.x = element_text(margin = margin(t = 10)),
    axis.ticks.y = element_blank()
  ) +
  labs(color = NULL)

# Print Figure I.3
fig_i3_citiz_in_plot<-ggarrange(fig_i3_m1_citiz_in_plot, NULL, fig_i3_m2_citiz_in_plot,
                                nrow = 1, common.legend = F, legend = NULL, ncol = 3, widths = c(1, 0.09, 1))
fig_i3_citiz_in_plot<-annotate_figure(fig_i3_citiz_in_plot, top = text_grob("Target (citizenship) in-group", size = 14))
fig_i3_citiz_out_plot<-ggarrange(fig_i3_m1_citiz_out_plot, NULL, fig_i3_m2_citiz_out_plot,
                                 nrow = 1, common.legend = T, legend = "bottom", ncol = 3, widths = c(1, 0.09, 1))
fig_i3_citiz_out_plot<-annotate_figure(fig_i3_citiz_out_plot, top = text_grob("Target (citizenship) out-group", size = 14))
pdf('figure_i3.pdf', width = 8.26, height = 5.82)
ggarrange(fig_i3_citiz_in_plot, fig_i3_citiz_out_plot,
          nrow = 2, common.legend = T, legend = "bottom", ncol=1, heights = c(1, 1.1))
dev.off()

# =============================================================================
# Figure I.4: Interaction Effects Elite Cue (Partisanship), Respondents’ Disapproval
# =============================================================================

# Convert regression variables into factors
factor_vars <- c("agent", "type", "scope", "targ_nonstate",
                 "perp_match", "targ_race_match", "targ_relig_match", 
                 "targ_citiz_match", "frame", "elite_perp", "elite_targ_race", 
                 "elite_targ_citiz", "elite_targ_relig","elite_match")
hr_survey[factor_vars] <- lapply(hr_survey[factor_vars], as.factor)

# -----------------------------------------------------------------------------
# Calculate marginal means interactions
# -----------------------------------------------------------------------------

# Model 1
fig_i4_m1 <- cregg::cj(hr_survey, outcome1 ~ agent + type + scope + targ_nonstate + perp_match + targ_race_match + targ_relig_match + targ_citiz_match + frame + elite_perp + elite_targ_race + elite_targ_relig + elite_targ_citiz, id = ~id, estimate = "mm", by = ~elite_match)

# Model 2
fig_i4_m2 <- cregg::cj(hr_survey, outcome2 ~ agent + type + scope + targ_nonstate + perp_match + targ_race_match + targ_relig_match + targ_citiz_match + frame + elite_perp + elite_targ_race + elite_targ_relig + elite_targ_citiz, id = ~id, estimate = "mm", by = ~elite_match)

# Subset group identity dummy variables
interaction_terms <- c("elite_perp", "elite_targ_race", "elite_targ_relig", "elite_targ_citiz")
fig_i4_m1 <- fig_i4_m1[fig_i4_m1$feature %in% interaction_terms,]
fig_i4_m2 <- fig_i4_m2[fig_i4_m2$feature %in% interaction_terms,]

# Exclude NA values
fig_i4_m1 <- fig_i4_m1[!is.na(fig_i4_m1$estimate),]
fig_i4_m2 <- fig_i4_m2[!is.na(fig_i4_m2$estimate),]

# -----------------------------------------------------------------------------
# Prepare Figures
# -----------------------------------------------------------------------------

# Combine models
fig_i4_all <- rbind(fig_i4_m1, fig_i4_m2) 

# Create group identity variable labels
variable_labels <- c("perp_match" = "Perpetrator (partisanship)",
                     "targ_race_match" = "Target (race)",
                     "targ_relig_match" = "Target (religion)",
                     "targ_citiz_match" = "Target (citizenship)")
fig_i4_all <- dplyr::bind_rows(
  fig_i4_all,
  do.call(rbind, lapply(names(variable_labels), function(variable) {
    data.frame(
      outcome = c("outcome1", "outcome2"),
      variable = variable_labels[variable],
      level = variable_labels[variable],
      estimate = NA, lower = NA, upper = NA
    )
  }))
)

# Set factor order
fig_i4_all_elite_in <- filter(fig_i4_all, !grepl("elite_out", level))
fig_i4_all_elite_in <- fig_i4_all_elite_in %>%
  mutate(level = factor(level, levels = c("Perpetrator (partisanship)", "elite_in_perp_in", "elite_in_perp_out",
                                          "Target (race)", "elite_in_race_in", "elite_in_race_out",
                                          "Target (religion)", "elite_in_relig_in", "elite_in_relig_out",
                                          "Target (citizenship)", "elite_in_citiz_in", "elite_in_citiz_out")) %>% fct_rev())
fig_i4_all_elite_out <- filter(fig_i4_all, !grepl("elite_in", level))
fig_i4_all_elite_out <- fig_i4_all_elite_out %>%
  mutate(level = factor(level, levels = c("Perpetrator (partisanship)", "elite_out_perp_in", "elite_out_perp_out",
                                          "Target (race)", "elite_out_race_in", "elite_out_race_out",
                                          "Target (religion)", "elite_out_relig_in", "elite_out_relig_out",
                                          "Target (citizenship)", "elite_out_citiz_in", "elite_out_citiz_out" )) %>% fct_rev())

# Create respondents variable (in-groups vs. out-groups)
fig_i4_all_elite_in <- fig_i4_all_elite_in %>%
  mutate(Respondents = case_when(
    grepl("_in$", level) ~ "In-group",   
    grepl("_out$", level) ~ "Out-group", 
    level %in% c("Perpetrator (partisanship)", "Target (race)", 
                 "Target (religion)", "Target (citizenship)") ~ "In-group", 
    TRUE ~ level
  )) %>%
  mutate(Respondents = factor(Respondents, levels = c("In-group", "Out-group")))
fig_i4_all_elite_out <- fig_i4_all_elite_out %>%
  mutate(Respondents = case_when(
    grepl("_out$", level) ~ "Out-group",  
    grepl("_in$", level) ~ "In-group",  
    level %in% c("Perpetrator (partisanship)", "Target (race)", 
                 "Target (religion)", "Target (citizenship)") ~ "In-group", 
    TRUE ~ level
  )) %>%
  mutate(Respondents = factor(Respondents, levels = c("In-group", "Out-group")))

# Separate models
fig_i4_m1_elite_in <- filter(fig_i4_all_elite_in, outcome == "outcome1")
fig_i4_m2_elite_in <- filter(fig_i4_all_elite_in, outcome == "outcome2")
fig_i4_m1_elite_out <- filter(fig_i4_all_elite_out, outcome == "outcome1")
fig_i4_m2_elite_out <- filter(fig_i4_all_elite_out, outcome == "outcome2")

# -----------------------------------------------------------------------------
# Create Figures
# -----------------------------------------------------------------------------

# Create panel (a) Elite in-group - disapproval forced-choice
fig_i4_m1_elite_in_plot <- ggplot(fig_i4_m1_elite_in, aes(x = level, y = estimate, colour = Respondents)) +
  geom_point() +
  geom_errorbar(aes(ymin = lower, ymax = upper), size = 0.3, width = 0.2) +
  scale_x_discrete(labels = c(
    "", "Target (citizenship)", "", 
    "", "Target (religion)", "",
    "", "Target (race)", "", 
    "", "Perpetrator (partisanship)", ""
  )) +
  xlab('') + ylab('Marginal mean') +
  coord_flip() +
  geom_hline(yintercept = 0.5, size = 0.2, color = "black") +
  scale_y_symmetric(mid = 0.5) +
  theme_classic(base_size = 10) +
  scale_colour_grey() +
  easy_center_title() +
  ggtitle("(a) Disapproval forced-choice") +
  theme(
    axis.text.x = element_text(colour = "black"),
    axis.text.y = element_text(colour = "black"),
    axis.title.x = element_text(margin = margin(t = 10)),
    axis.ticks.y = element_blank(),
    legend.position = "none"
  ) +
  labs(color = NULL)

# Create panel (b) Elite in-group - disapproval ratings-based
fig_i4_m2_elite_in_plot <- ggplot(fig_i4_m2_elite_in, aes(x = level, y = estimate, colour = Respondents)) +
  geom_point() +
  geom_errorbar(aes(ymin = lower, ymax = upper), size = 0.3, width = 0.2) +
  scale_x_discrete(labels = c(
    "", "Target (citizenship)", "", 
    "", "Target (religion)", "",
    "", "Target (race)", "", 
    "", "Perpetrator (partisanship)", ""
  )) +
  xlab('') + ylab('Marginal mean') +
  coord_flip(ylim=c(0.66, 0.74)) +
  theme_classic(base_size = 10) +
  scale_colour_grey() +
  easy_center_title() +
  ggtitle("(b) Disapproval ratings-based") +
  theme(
    axis.text.x = element_text(colour = "black"),
    axis.text.y = element_text(colour = "black"),
    axis.title.x = element_text(margin = margin(t = 10)),
    axis.ticks.y = element_blank(),
    legend.position = "none"
  ) +
  labs(color = NULL)

# Create panel (c) Elite out-group - disapproval forced choice
fig_i4_m1_elite_out_plot <- ggplot(fig_i4_m1_elite_out, aes(x = level, y = estimate, colour = Respondents)) +
  geom_point() +
  geom_errorbar(aes(ymin = lower, ymax = upper), size = 0.3, width = 0.2) +
  scale_x_discrete(labels = c(
    "", "Target (citizenship)", "", 
    "", "Target (religion)", "",
    "", "Target (race)", "", 
    "", "Perpetrator (partisanship)", ""
  )) +
  xlab('') + ylab('Marginal mean') +
  coord_flip() +
  geom_hline(yintercept = 0.5, size = 0.2, color = "black") +
  scale_y_symmetric(mid = 0.5) +
  theme_classic(base_size = 10) +
  scale_colour_grey() +
  easy_center_title() +
  ggtitle("(c) Disapproval forced-choice") +
  theme(
    axis.text.x = element_text(colour = "black"),
    axis.text.y = element_text(colour = "black"),
    axis.title.x = element_text(margin = margin(t = 10)),
    axis.ticks.y = element_blank()
  ) +
  labs(color = NULL)

# Create panel (d) Elite out-group - disapproval ratings-based
fig_i4_m2_elite_out_plot <- ggplot(fig_i4_m2_elite_out, aes(x = level, y = estimate, colour = Respondents)) +
  geom_point() +
  geom_errorbar(aes(ymin = lower, ymax = upper), size = 0.3, width = 0.2) +
  scale_x_discrete(labels = c(
    "", "Target (citizenship)", "", 
    "", "Target (religion)", "",
    "", "Target (race)", "", 
    "", "Perpetrator (partisanship)", ""
  )) +
  xlab('') + ylab('Marginal mean') +
  coord_flip(ylim=c(0.66, 0.74)) +
  theme_classic(base_size = 10) +
  scale_colour_grey() +
  easy_center_title() +
  ggtitle("(d) Disapproval ratings-based") +
  theme(
    axis.text.x = element_text(colour = "black"),
    axis.text.y = element_text(colour = "black"),
    axis.title.x = element_text(margin = margin(t = 10)),
    axis.ticks.y = element_blank()
  ) +
  labs(color = NULL)

# Print Figure I.4
fig_i4_elite_in_plot<-ggarrange(fig_i4_m1_elite_in_plot, NULL, fig_i4_m2_elite_in_plot,
                                nrow = 1, common.legend = F, legend = NULL, ncol = 3, widths = c(1, 0.09, 1))
fig_i4_elite_in_plot<-annotate_figure(fig_i4_elite_in_plot, top = text_grob("Elite cue (partisanship) in-group", size = 14))
fig_i4_elite_out_plot<-ggarrange(fig_i4_m1_elite_out_plot, NULL, fig_i4_m2_elite_out_plot,
                                 nrow = 1, common.legend = T, legend = "bottom", ncol = 3, widths = c(1, 0.09, 1))
fig_i4_elite_out_plot<-annotate_figure(fig_i4_elite_out_plot, top = text_grob("Elite cue (partisanship) out-group", size = 14))
pdf('figure_i4.pdf', width = 8.26, height = 5.82)
ggarrange(fig_i4_elite_in_plot, fig_i4_elite_out_plot,
          nrow = 2, common.legend = T, legend = "bottom", ncol=1, heights = c(1, 1.1))
dev.off()